﻿<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>第23章. 示例、教程、案例研究</title>
<link rel="stylesheet" href="css/espertech.css" type="text/css">
	<meta name="generator" content="DocBook XSL-NS Stylesheets V1.74.0">
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
			<link rel="home" href="index.html" title="Esper参考手册">
				<link rel="up" href="index.html" title="Esper参考手册">
					<link rel="prev" href="extension.html" title="第22章. 集成与扩展">
						<link rel="next" href="performance.html" title="第24章. 性能">
</head>

<body>
	<p id="title">
		<a href="./index.html" class="site_href"><strong>www.espertech.com</strong></a><a href="http://www.espertech.com/esper/esper-documentation/" class="doc_href"><strong>文档</strong></a>
	</p>
	<ul class="docnav">
		<li class="previous"><a accesskey="p" href="extension.html"><strong>上一章</strong></a></li>
		<li class="next"><a accesskey="n" href="performance.html"><strong>下一章</strong></a></li>
	</ul>
	<div class="chapter" lang="en-US">
		<div class="titlepage">
			<div>
				<div>
					<h2 class="title"><a id="examples"></a>第23章. 示例、教程、案例研究</h2>
				</div>
			</div>
		</div>
		<div class="toc">
			<dl>
				<dt><a href="examples.html#examples-overview">23.1. 示例概述</a></dt>
				<dt><a href="examples.html#examples-running">23.2. 运行示例</a></dt>
				<dt><a href="examples.html#examples-autoid">23.3. 自动识别RFID阅读器</a></dt>
				<dt><a href="examples.html#examples-runtimeconfig">23.4. 运行时配置</a></dt>
				<dt><a href="examples.html#examples-servershell">23.5. JMS服务器外壳和客户端</a></dt>
				<dd>
					<dl>
						<dt><a href="examples.html#examples-servershell-processes">23.5.1. 概述</a></dt>
						<dt><a href="examples.html#examples-servershell-jmsevents">23.5.2. 将JMS消息作为事件</a></dt>
						<dt><a href="examples.html#examples-servershell-jmx">23.5.3. 用于远程动态语句管理的JMX</a></dt>
					</dl>
				</dd>
				<dt><a href="examples.html#examples-marketdata-monitor">23.6. 市场数据馈送监控</a></dt>
				<dd>
					<dl>
						<dt><a href="examples.html#examples-marketdata-monitor-input">23.6.1. 输入事件</a></dt>
						<dt><a href="examples.html#examples-marketdata-computing">23.6.2. 计算每个馈送的速率</a></dt>
						<dt><a href="examples.html#examples-marketdata-falloff">23.6.3. 检测下降情况</a></dt>
						<dt><a href="examples.html#examples-marketdata-monitor-sim">23.6.4. 事件生成器</a></dt>
					</dl>
				</dd>
				<dt><a href="examples.html#examples-ohlcpluginview">23.7. OHLC插件数据窗口</a></dt>
				<dt><a href="examples.html#examples-transaction-3-event-challenge">23.8. 交易三事件挑战</a></dt>
				<dd>
					<dl>
						<dt><a href="examples.html#examples-txn3event-1">23.8.1. 事件</a></dt>
						<dt><a href="examples.html#examples-txn3event-2">23.8.2. 组合事件</a></dt>
						<dt><a href="examples.html#examples-txn3event-3">23.8.3. 实时汇总数据</a></dt>
						<dt><a href="examples.html#examples-txn3event-4">23.8.4. 查找问题</a></dt>
						<dt><a href="examples.html#examples-txn3event-5">23.8.5. 事件生成器</a></dt>
					</dl>
				</dd>
				<dt><a href="examples.html#examples-terminalsvc-J2EE">23.9. 自助服务终端</a></dt>
				<dd>
					<dl>
						<dt><a href="examples.html#examples-terminalsvc-events">23.9.1. 事件</a></dt>
						<dt><a href="examples.html#examples-terminalsvc-pattern1">23.9.2. 检测客户签到问题</a></dt>
						<dt><a href="examples.html#examples-terminalsvc-pattern2">23.9.3. 状态事件缺失</a></dt>
						<dt><a href="examples.html#examples-terminalsvc-epl1">23.9.4. 活动汇总数据</a></dt>
						<dt><a href="examples.html#examples-terminalsvc-j2ee">23.9.5. J2EE应用服务器示例应用程序</a></dt>
					</dl>
				</dd>
				<dt><a href="examples.html#examples-assets-moving">23.10. 资产跨区域移动 - 一个RFID示例</a></dt>
				<dt><a href="examples.html#examples-stockticker">23.11. 股票行情显示器</a></dt>
				<dt><a href="examples.html#examples-matchmaker">23.12. 匹配器</a></dt>
				<dt><a href="examples.html#examples-namedwindowquery">23.13. 命名窗口查询</a></dt>
				<dt><a href="examples.html#examples-virtualdw">23.14. 示例虚拟数据窗口</a></dt>
				<dt><a href="examples.html#examples-cycledetect">23.15. 示例循环检测</a></dt>
				<dt><a href="examples.html#examples-qossla">23.16. 服务质量</a></dt>
				<dt><a href="examples.html#examples-trivia">23.17. 冷知识极客俱乐部</a></dt>
			</dl>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-overview"></a>23.1. 示例概述</h2>
					</div>
				</div>
			</div>
			<p>
				本章概述了发行版中 <code class="literal">examples</code> 文件夹下随附的示例。每个示例都位于一个单独的文件夹中，该文件夹包含示例所需的所有文件（不包括jar文件）。
			</p>
			<p>以下是按字母顺序对示例的概述：</p>
			<div class="table">
				<a id="d0e56135"></a>
				<p class="title">
					<b>表23.1. 示例</b>
				</p>
				<div class="table-contents">
					<table summary="示例" border="1">
						<colgroup>
							<col>
								<col>
						</colgroup>
						<thead>
							<tr>
								<th>名称</th>
								<th>描述</th>
							</tr>
						</thead>
						<tbody>
							<tr>
								<td><a class="xref" href="examples.html#examples-autoid" title="23.3. 自动识别RFID阅读器">23.3节，“自动识别RFID阅读器”</a></td>
								<td>
									<p>当托盘进入其中一个RFID阅读器的范围时，一组RFID阅读器会感应到RFID标签。</p>
									<p>展示了XSD模式和XML事件表示的使用。一条语句展示了滚动时间窗口、对嵌套属性的where子句过滤以及分组操作。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-marketdata-monitor" title="23.6. 市场数据馈送监控">23.6节，“市场数据馈送监控”</a></td>
								<td>
									<p>处理原始市场数据馈送，报告吞吐量统计信息，并检测数据馈送速率何时意外下降。</p>
									<p>演示了带有having子句的批处理时间窗口和滚动时间窗口。这是一个多线程示例，具有可配置的线程数量，并且有一个用于生成馈送数据的模拟器。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-matchmaker" title="23.12. 匹配器">23.12节，“匹配器”</a></td>
								<td>
									<p>在“匹配器”示例中，每个移动用户都有一个X和Y位置，此示例创建的事件模式的任务是检测在给定范围内且某些属性与偏好匹配的移动用户。</p>
									<p>使用重叠上下文根据移动用户事件查找匹配的移动用户。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-namedwindowquery" title="23.13. 命名窗口查询">23.13节，“命名窗口查询”</a></td>
								<td>
									<p>一个处理温度传感器事件的小型基准测试。该示例创建一个命名窗口，并向其中填充大量事件。然后，它执行大量预编译的语句以及即发即弃查询，并报告时间。</p>
									<p>如果您对命名窗口、Map事件类型表示、即发即弃查询以及通过on-select预定义的语句以及性能方面感兴趣，请研究此示例。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-virtualdw" title="23.14. 示例虚拟数据窗口">23.14节，“示例虚拟数据窗口”</a></td>
								<td>
									<p>此示例演示了使用虚拟数据窗口来公开（大型）外部数据存储，无需在内存中保留事件，并且不会牺牲语句性能。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-cycledetect" title="23.15. 示例循环检测">23.15节，“示例循环检测”</a></td>
								<td>
									<p>此示例展示了聚合多功能扩展API，用于解决循环检测问题，检测账户之间交易中的循环。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-ohlcpluginview" title="23.7. OHLC插件数据窗口">23.7节，“OHLC插件数据窗口”</a></td>
								<td>
									<p>一个插件自定义数据窗口，解决了金融领域的一个问题：根据每个事件的时间戳，为可能延迟到达的事件的分钟间隔计算开盘价、最高价、最低价和收盘价。</p>
									<p>基于扩展API的自定义插件数据窗口可以是一种方便且可重用的方式，将特定领域的分析问题表示为一个单元，并且此示例包括OHLC数据窗口工厂和窗口的代码以及用于测试该窗口的模拟器。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="performance.html#performance-kit" title="24.3. 使用性能工具包">24.3节，“使用性能工具包”</a></td>
								<td>
									<p>一个基准测试，在本文档的性能部分的“性能工具包”下有更详细的描述。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-qossla" title="23.16. 服务质量">23.16节，“服务质量”</a></td>
								<td>
									<p>此示例开发了一些代码，用于测量服务质量水平，例如服务级别协议 (SLA) 的质量水平。</p>
									<p>
										此示例将模式与select语句相结合，展示了定时器 <code class="literal">'at'</code> 操作符和跟随操作符 <code class="literal">-&gt;</code> 的使用，并使用迭代器API轮询当前结果。
									</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-assets-moving" title="23.10. 资产跨区域移动 - 一个RFID示例">23.10节，“资产跨区域移动 - 一个RFID示例”</a></td>
								<td>
									<p>一个来自RFID领域的示例，处理位置报告事件。该示例包括一个简单的基于Swing的图形用户界面 (GUI) 用于可视化，允许直观地将标签从一个区域移动到另一个区域。它还包含一个全面的模拟器，用于为大量资产组及其跟踪生成数据。</p>
									<p>该示例使用非重叠上下文来检测聚合数据中的模式，以确定资产组约束何时被违反。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-runtimeconfig" title="23.4. 运行时配置">23.4节，“运行时配置”</a></td>
								<td>
									<p>示例代码，用于演示各种关键的编译时和运行时操作，例如动态添加事件类型、添加新变量、添加插件单行函数和聚合函数以及添加变体流。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-servershell" title="23.5. JMS服务器外壳和客户端">23.5节，“JMS服务器外壳和客户端”</a></td>
								<td>
									<p>服务器外壳是一个基于Java消息服务 (JMS) 的服务器和客户端，它在JMS目标上发送和监听消息。它还演示了一个用于远程语句管理的简单Java管理扩展 (JMX) MBean。</p>
									<p>一条语句在滚动时间窗口上计算每个IP地址的平均持续时间，并每2秒输出一次快照。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-stockticker" title="23.11. 股票行情显示器">23.11节，“股票行情显示器”</a></td>
								<td>
									<p>一个来自金融领域的示例，其特点是使用事件模式根据价格和符号过滤股票行情事件。该示例旨在提供大量事件，并且包括多线程单元测试代码以及模拟数据生成器。</p>
									<p>该示例使用重叠上下文根据接收到的价格限制事件来查找价格飙升的时间。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-terminalsvc-J2EE" title="23.9. 自助服务终端">23.9节，“自助服务终端”</a></td>
								<td>
									<p>一个基于J2EE的机场自助服务终端管理系统，它从连接的终端接收大量事件。</p>
									<p>包含一个用于J2EE容器的消息驱动bean (EJB-MDB)、一个客户端和一个模拟器，以及用于检测各种条件的语句。也提供了一个在J2EE容器外部运行的版本。</p>
								</td>
							</tr>
							<tr>
								<td><a class="xref" href="examples.html#examples-trivia" title="23.17. 冷知识极客俱乐部">23.17节，“冷知识极客俱乐部”</a></td>
								<td>
									<p>“冷知识极客俱乐部”演示了用于计分系统的EPL，在冷知识游戏中计算分数。</p>
								</td>
							</tr>
						</tbody>
					</table>
				</div>
			</div>
			<br class="table-break">
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-running"></a>23.2. 运行示例</h2>
					</div>
				</div>
			</div>
			<p>为了编译和运行这些示例，请按照以下说明操作：</p>
			<div class="orderedlist">
				<ol>
					<li>
						<p>确保已安装Java 1.6或更高版本，并且已设置JAVA_HOME环境变量。</p>
					</li>
					<li>
						<p>
							打开一个控制台窗口，并将目录更改为examples/<span class="emphasis"><em>示例名称</em></span>/etc。
						</p>
					</li>
					<li>
						<p>运行 "setenv.bat"（Windows）或 "setenv.sh"（Unix）以验证您的环境设置。</p>
					</li>
					<li>
						<p>运行 "compile.bat"（Windows）或 "compile.sh"（Unix）以编译一个示例。</p>
					</li>
					<li>
						<p>现在您已准备好运行一个示例。一些示例需要必填参数，这些参数也在“etc”文件夹中的“readme.txt”文件中进行了描述。</p>
					</li>
					<li>
						<p>在“log4j.xml”配置文件中修改日志记录器的日志级别，在类或包级别将DEBUG更改为INFO，以控制文本输出的数量。</p>
					</li>
				</ol>
			</div>
			<p>
				每个示例还提供了Eclipse项目的 <code class="literal">.classpath</code> 和 <code class="literal">.project</code> 文件。Eclipse项目需要一个 <code class="literal">esper_runtime</code> 用户库，其中包含运行时依赖项。
			</p>
			<p>
				示例代码存在JUnit测试。示例的JUnit测试源代码可以在每个示例的 <code class="literal">src/test</code> 文件夹中找到。要构建和运行示例的JUnit测试，请使用Maven 2目标 <code class="literal">test</code>。
			</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-autoid"></a>23.3. 自动识别RFID阅读器</h2>
					</div>
				</div>
			</div>
			<p>在这个示例中，当托盘进入其中一个RFID阅读器的范围时，一组RFID阅读器会感应到RFID标签。 一个阅读器会生成包含观测信息的XML文档，例如阅读器传感器ID、观测时间和观测到的标签。一条语句计算在过去60秒内每个阅读器传感器ID对应的标签总数。</p>
			<p>
				此示例演示了如何将解组为 <code class="literal">org.w3c.dom.Node</code> DOM文档节点的XML文档，由运行时原生处理，而无需Java对象事件表示。该示例使用XPath表达式作为事件属性，用于统计传感器观测到的标签数量。这些XML文档遵循自动识别（<code class="literal">http://www.autoid.org/</code>）组织的标准。
			</p>
			<p>
				此示例的类可以在包 <code class="literal">com.espertech.esper.example.autoid</code> 中找到。 由于事件是没有Java对象表示的XML文档，所以该示例没有事件类。
			</p>
			<p>此示例还提供了一个可以从命令行运行的模拟器。 该模拟器根据命令行参数指定的数量生成一些XML文档，并打印出每个传感器的总数。 运行 "run_autoid.bat"（Windows）或 "run_autoid.sh"（Unix）以启动自动识别模拟器。 请参阅同一文件夹中的自述文件以获取构建说明和命令行参数。</p>
			<p>
				下面的代码片段展示了计算每个传感器的标签总数的简单语句。该语句由类 <code class="literal">com.espertech.esper.example.autoid.RFIDTagsPerSensorStmt</code> 创建。
			</p>
			<pre class="">select ID as sensorId, sum(countTags) as numTagsPerSensor
from AutoIdRFIDExample#time(60 seconds)
where Observation[0].Command = 'READ_PALLET_TAGS_ONLY'
group by ID</pre>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-runtimeconfig"></a>23.4. 运行时配置</h2>
					</div>
				</div>
			</div>
			<p>此示例演示了各种关键的运行时配置选项，例如动态添加事件类型、添加新变量、添加插件单行函数和聚合函数以及添加变体流。</p>
			<p>
				此示例的类位于包 <code class="literal">com.espertech.esper.example.runtimeconfig</code> 中。
			</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-servershell"></a>23.5. JMS服务器外壳和客户端</h2>
					</div>
				</div>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-servershell-processes"></a>23.5.1. 概述</h3>
						</div>
					</div>
				</div>
				<p>服务器外壳是一个基于Java消息服务 (JMS) 的服务器，它监听JMS目标上的消息，并将接收到的事件发送到运行时。该示例还演示了一个Java管理扩展 (JMX) MBean，它允许远程动态语句管理。此服务器设计为可以与Tibco (TM) 企业消息系统 (Tibco EMS) 或Apache ActiveMQ一起运行，由一个属性文件控制。</p>
				<p>服务器外壳是作为EsperIO Spring JMSTemplate适配器的替代品创建的。服务器外壳是一个用于字节消息的低延迟处理器。它使用JMS监听器在多个线程中处理消息，这种模型减少了许多JMS提供程序的线程上下文切换。该服务器是可配置的，并且已经在两个JMS提供程序上进行了测试。它仅由10个类组成，因此易于理解。</p>
				<p>服务器外壳示例附带一个客户端（服务器外壳客户端），该客户端将事件发送到基于JMS的服务器，并且还通过JMX MBean代理类在服务器上远程创建一条语句。</p>
				<p>
					此示例的服务器外壳类位于包 <code class="literal">com.espertech.esper.example.servershell</code> 中。 通过更改 <code class="literal">etc</code> 文件夹中的 <code class="literal">servershell_config.properties</code> 文件中的属性，将服务器配置为指向您的JMS提供程序。 确保您的JMS提供程序（ActiveMQ或Tibco EMS）正在运行，然后运行 "run_servershell.bat"（Windows）或 "run_servershell.sh"（Unix）以启动JMS服务器。
				</p>
				<p>在启动客户端之前，请先启动服务器外壳进程，因为客户端还通过连接到服务器进程来演示通过JMX进行的远程语句管理。</p>
				<p>
					服务器外壳的客户端类可以在包 <code class="literal">com.espertech.esper.example.servershellclient</code> 中找到。 客户端与服务器外壳共享相同的配置文件。 运行 "run_servershellclient.bat"（Windows）或 "run_servershellclient.sh"（Unix）以启动JMS生产者客户端，该客户端也包括一个JMX客户端。
				</p>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-servershell-jmsevents"></a>23.5.2. 将JMS消息作为事件</h3>
						</div>
					</div>
				</div>
				<p>
					服务器外壳启动可配置数量的JMS <code class="literal">MessageListener</code> 实例，这些实例监听给定的JMS目标。监听器期望接收到一个包含字符串有效负载的 <code class="literal">BytesMessage</code>。有效负载由一个IP地址和一个双精度类型的持续时间值组成，两者用逗号分隔。
				</p>
				<p>每个监听器提取消息的有效负载，构造一个事件对象，并将该事件发送到共享的运行时实例中。</p>
				<p>在启动时，服务器在运行时中创建一条单一语句，该语句打印出过去10秒内每个IP地址的平均持续时间事件，并指定输出速率为2秒。通过先运行服务器然后运行客户端，您可以每2秒看到平均值的输出。</p>
				<p>服务器外壳客户端充当JMS生产者，发送1000个具有随机IP地址和持续时间的事件。</p>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-servershell-jmx"></a>23.5.3. 用于远程动态语句管理的JMX</h3>
						</div>
					</div>
				</div>
				<p>服务器外壳也是一个JMX服务器，提供基于RMI的连接器。服务器外壳公开一个JMX MBean，允许进行远程语句管理。该JMX MBean允许远程创建一条语句、将一个监听器附加到该语句以及远程取消部署一条语句。</p>
				<p>服务器外壳客户端在启动时，获取服务器外壳公开的管理MBean的远程实例。它通过MBean创建一条语句，该语句过滤掉所有大于9.9的值的持续时间。 在发送1000个事件后，客户端然后在服务器上远程取消部署该语句。</p>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-marketdata-monitor"></a>23.6. 市场数据馈送监控</h2>
					</div>
				</div>
			</div>
			<p>此示例处理原始市场数据馈送。它报告吞吐量统计信息，并检测数据馈送速率何时意外下降。数据速率下降可能意味着数据已过时，并且当馈送可能存在问题时您需要发出警报。</p>
			<p>
				此示例的类位于包 <code class="literal">com.espertech.esper.example.marketdatafeed</code> 中。 在 <code class="literal">examples/etc</code> 文件夹中运行 "run_mktdatafeed.bat"（Windows）或 "run_mktdatafeed.sh"（Unix）以启动市场数据馈送模拟器。
			</p>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-marketdata-monitor-input"></a>23.6.1. 输入事件</h3>
						</div>
					</div>
				</div>
				<p>输入流由1个事件流组成，其中包含2个模拟的市场数据馈送。流中的每个单独事件指示提供市场数据的馈送、证券代码和一些定价信息：</p>
				<pre class="">String symbol;
FeedEnum feed;
double bidPrice;
double askPrice;</pre>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-marketdata-computing"></a>23.6.2. 计算每个馈送的速率</h3>
						</div>
					</div>
				</div>
				<p>为了获取吞吐量统计信息并检测快速下降，该示例为每个市场数据馈送计算每秒的滴答数速率。</p>
				<p>您可以使用一条语句，该语句在市场数据事件流上指定一个数据窗口，将1秒的事件批量处理在一起。 您指定馈送以及每个馈送的事件计数作为输出值。为了使这些数据可用于进一步处理，您将输出事件插入到TicksPerSecond事件流中：</p>
				<pre class="">insert into TicksPerSecond
select feed, count(*) as cnt 
  from MarketDataEvent#time_batch(1 second) 
 group by feed</pre>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-marketdata-falloff"></a>23.6.3. 检测下降情况</h3>
						</div>
					</div>
				</div>
				<p>我们将快速下降定义为，当任何一秒的每秒滴答数低于过去10秒内每秒滴答数平均值的75%时发出警报。</p>
				<p>我们可以简单地使用先前语句计算的TicksPerSecond事件来计算过去10秒内每秒滴答数的平均值，并对过去10秒取平均值。接下来，该示例将当前速率与移动平均值进行比较，并过滤掉任何低于平均值75%的速率：</p>
				<pre class="">select feed, avg(cnt) as avgCnt, cnt as feedCnt 
  from TicksPerSecond#time(10 seconds)
 group by feed 
having cnt &lt; avg(cnt) * 0.75</pre>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-marketdata-monitor-sim"></a>23.6.4. 事件生成器</h3>
						</div>
					</div>
				</div>
				<p>模拟器为2个馈送（馈送A和馈送B）生成市场数据事件。 模拟器的第一个参数是线程数量。每个线程在一个无限循环中为每个馈送发送事件。 请注意，当Java虚拟机垃圾回收启动时，该示例在这样的暂停期间会生成速率下降情况。</p>
				<p>第二个参数是速率下降概率参数，它以百分比指定模拟器将随机选择的馈送的速率降低到该秒目标速率的60%的概率。因此，可以生成速率下降警报。</p>
				<p>第三个参数定义运行该示例的秒数。</p>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-ohlcpluginview"></a>23.7. OHLC插件数据窗口</h2>
					</div>
				</div>
			</div>
			<p>本示例包含一个基于扩展API的完整自定义数据窗口，用于为提供长整型时间戳和双精度型值的事件计算OHLC（开盘价、最高价、最低价、收盘价）柱状图数据。</p>
			<p>OHLC柱状图源于金融领域的问题。“开盘价”指的是一个时间间隔内的第一个数据点，“收盘价”指的是最后一个数据点。“最高价”指的是每个时间间隔内的最大值，“最低价”指的是最小值。“柱状图”一词用于描述这4个值在每个时间间隔的结果。</p>
			<p>本示例提供了一个硬编码为1分钟柱状图的OHLC数据窗口。它依据每个事件携带的时间戳值，而非系统时间。事件不再被纳入某个柱状图计算的截止时间被硬编码为5秒。</p>
			<p>该窗口假定事件按时间戳顺序到达：每个事件的时间戳值等于或大于前一个事件提供的时间戳值。</p>
			<p>
				该窗口也可与 <code class="literal">#groupwin</code> 一起使用，以便按条件（如符号）进行分组。在这种情况下，时间戳顺序的假设适用于每个符号。
			</p>
			<p>该窗口能够妥善处理无事件和事件延迟的情况。时间间隔边界由系统时间定义，因此事件时间戳和系统时间必须大致同步，除非使用外部定时器事件。</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-transaction-3-event-challenge"></a>23.8. 交易三事件挑战</h2>
					</div>
				</div>
			</div>
			<p>
				本示例的类位于 <code class="literal">com.espertech.esper.example.transaction</code> 包中。 运行“run_txnsim.bat”（Windows系统）或“run_txnsim.sh”（Unix系统）启动交易模拟器。 构建说明和命令行参数请查看同一文件夹中的README文件。
			</p>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-txn3event-1"></a>23.8.1. 事件</h3>
						</div>
					</div>
				</div>
				<p>本用例涉及跟踪交易的三个组成部分。示例使用至少三个组成部分很重要，因为某些运行时对于每个交易仅处理两个事件时，性能或编码方式会有所不同。每个组成部分作为一个事件进入运行时，包含以下字段：</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>交易ID</p>
						</li>
						<li>
							<p>时间戳</p>
						</li>
					</ul>
				</div>
				<p>此外，本示例还有以下额外字段：</p>
				<p>事件A中：</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>客户ID</p>
						</li>
					</ul>
				</div>
				<p>事件C中：</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>供应商ID（订单通过其完成交付的供应商的ID）</p>
						</li>
					</ul>
				</div>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-txn3event-2"></a>23.8.2. 组合事件</h3>
						</div>
					</div>
				</div>
				<p>我们需要接收事件A、B和C，并生成一个包含以下字段的单一组合事件：</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>交易ID</p>
						</li>
						<li>
							<p>客户ID</p>
						</li>
						<li>
							<p>事件A的时间戳</p>
						</li>
						<li>
							<p>事件B的时间戳</p>
						</li>
						<li>
							<p>事件C的时间戳</p>
						</li>
					</ul>
				</div>
				<p>我们在此处要做的是匹配每个事件上的交易ID，以形成一个聚合事件。如果所有这些事件都在关系型数据库中，这可以通过简单的SQL连接来完成…… 但如果每秒有10000个事件，那么你需要强大的数据库硬件才能实现。</p>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-txn3event-3"></a>23.8.3. 实时汇总数据</h3>
						</div>
					</div>
				</div>
				<p>此外，本示例还生成以下内容：</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>在过去30分钟内，事件的最小、最大、平均总延迟（事件A和C之间的时间差）。</p>
						</li>
						<li>
							<p>按（a）客户ID和（b）供应商ID分组的最小、最大、平均延迟。换句话说，就是来自每个客户和发往每个供应商的订单延迟指标。</p>
						</li>
						<li>
							<p>事件A/B（B的时间戳减去A的时间戳）和B/C（C的时间戳减去B的时间戳）之间的最小、最大、平均延迟。</p>
						</li>
					</ul>
				</div>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-txn3event-4"></a>23.8.4. 查找问题</h3>
						</div>
					</div>
				</div>
				<p>本示例检测未能完整包含三个事件的交易。换句话说，就是有事件A或B，但没有事件C的交易。需要注意的是，在这种情况下，你关注的是事件C。事件A或B的缺失可能表明事件传输出现故障，应忽略不计。虽然事件C的缺失也可能是传输故障，但值得深入调查。</p>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-txn3event-5"></a>23.8.5. 事件生成器</h3>
						</div>
					</div>
				</div>
				<p>为了便于测试、标准化以及展示示例的工作原理，本示例包含一个事件生成器。该生成器根据以下规则为给定数量的交易生成事件：</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>每5000笔交易中有1笔会跳过事件A</p>
						</li>
						<li>
							<p>每1000笔交易中有1笔会跳过事件B</p>
						</li>
						<li>
							<p>每10000笔交易中有1笔会跳过事件C。</p>
						</li>
						<li>
							<p>交易标识符是随机生成的</p>
						</li>
						<li>
							<p>客户和供应商标识符是从两个列表中随机选择的</p>
						</li>
						<li>
							<p>每个事件的时间戳基于系统时间。在事件A和B之间以及B和C之间，会在时间上增加0到999。所以，预计每个事件之间的时间差约为500毫秒</p>
						</li>
						<li>
							<p>事件按如下所述随机打乱顺序</p>
						</li>
					</ul>
				</div>
				<p>为了增加难度，本示例中的交易事件并非按顺序到达。这段代码确保它们完全乱序到达。为此，示例将事件填充到一个桶中，当桶满时，对其进行洗牌操作。桶的大小设置为会使一些交易的事件分散在不同桶中。所以，你会得到一个相当随机的事件流，代表大型分布式基础设施中的最坏情况。</p>
				<p>生成器允许你更改桶的大小（小、中、大、更大、超大）。桶越大，在给定交易的两个事件之间可能出现的事件就越多，因此随着桶大小的增加，缓冲区、哈希表/索引和其他结构等性能特性将受到更多的考验。</p>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-terminalsvc-J2EE"></a>23.9. 自助服务终端</h2>
					</div>
				</div>
			</div>
			<p>该示例是关于一个基于J2EE的机场自助服务终端管理系统，它从连接的终端接收大量事件。事件速率大约为每秒500个事件。一些事件表示异常情况，如“纸张不足”或“终端故障”。其他事件则监控客户使用终端办理登机手续和打印登机牌时的活动情况。</p>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-terminalsvc-events"></a>23.9.1. 事件</h3>
						</div>
					</div>
				</div>
				<p>每个自助服务终端可以发布以下6种事件中的任意一种。</p>
				<div class="itemizedlist">
					<ul compact="compact">
						<li>
							<p>办理登机手续 - 表示客户开始办理登机手续的对话</p>
						</li>
						<li>
							<p>已取消 - 表示客户取消了办理登机手续的对话</p>
						</li>
						<li>
							<p>已完成 - 表示客户完成了办理登机手续的对话</p>
						</li>
						<li>
							<p>故障 - 表示终端检测到硬件问题</p>
						</li>
						<li>
							<p>纸张不足 - 表示终端纸张不足</p>
						</li>
						<li>
							<p>状态 - 表示终端状态，无论是否有活动，每分钟发布一次，作为终端的心跳信息</p>
						</li>
					</ul>
				</div>
				<p>所有事件都提供发布该事件的终端的信息以及一个时间戳。终端信息存储在一个名为“term”的属性中，并提供一个终端ID。由于所有事件都携带类似的信息，因此将每个事件建模为基类BaseTerminalEvent的一个子类，该基类将提供所有事件共享的终端信息。这使我们能够以多态的方式处理所有终端事件，也就是说，您可以像处理父事件类型一样处理派生事件类型。这有助于简化我们的语句。</p>
				<p>所有终端每分钟发布一次状态事件。在正常情况下，状态事件表示终端处于活动且在线状态。状态事件的缺失可能表示终端由于某种原因离线，这可能需要进行调查。</p>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-terminalsvc-pattern1"></a>23.9.2. 检测客户办理登机手续问题</h3>
						</div>
					</div>
				</div>
				<p>当终端检测到硬件问题或网络中断时，客户可能正处于办理登机手续的过程中。在这种情况下，该示例会提醒工作人员帮助客户。当终端检测到问题时，它会发出一个“故障”事件。可以通过一个模式来查找终端显示故障且客户处于办理登机手续过程中的情况：</p>
				<pre class="">select * from pattern [ every a=Checkin -&gt; 
      ( OutOfOrder(term.id=a.term.id) and not 
          (Cancelled(term.id=a.term.id) or Completed(term.id=a.term.id)) )]</pre>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-terminalsvc-pattern2"></a>23.9.3. 状态事件缺失</h3>
						</div>
					</div>
				</div>
				<p>由于状态事件以60秒的固定间隔到达，您可以利用时间模式匹配结合定时器来查找未到达的事件。您可以使用“every”操作符和“timer:interval()”每60秒重复一个操作。然后将其与“not”操作符结合使用，以检查状态事件是否缺失。在65秒的时间间隔内查找状态事件，留出5秒来考虑可能的传输或处理延迟：</p>
				<pre class="">select 'terminal 1 is offline' from pattern 
  [every timer:interval(60 sec) -&gt; (timer:interval(65 sec) and not Status(term.id = 'T1'))]
output first every 5 minutes</pre>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-terminalsvc-epl1"></a>23.9.4. 活动汇总数据</h3>
						</div>
					</div>
				</div>
				<p>通过向我们的工作人员实时展示关于终端活动的统计信息，使他们能够监控系统并发现问题。下一个示例语句只是每1分钟为我们提供每种事件类型的计数。您可以进一步使用通过CountPerType事件流获得的数据，与记录的使用模式进行连接和比较，或者只是实时汇总活动情况。</p>
				<pre class="">insert into CountPerType
select type, count(*) as countPerType 
from BaseTerminalEvent#time(10 minutes) 
group by type
output all every 1 minutes</pre>
			</div>
			<div class="sect2" lang="en-US">
				<div class="titlepage">
					<div>
						<div>
							<h3 class="title"><a id="examples-terminalsvc-j2ee"></a>23.9.5. J2EE应用服务器示例应用程序</h3>
						</div>
					</div>
				</div>
				<p>发行包中的示例代码实现了一个消息驱动的企业Java Bean（MDB EJB）。该示例使用MDB作为通过JMS消息队列或主题处理传入事件的便捷方式。该示例使用2个JMS队列：一个队列接收终端发布的事件，第二个队列将通过语句和监听器检测到的情况反馈给接收进程。</p>
				<p>该示例已打包，可部署到JBoss Java应用服务器（请参阅http://www.jboss.org），并带有默认的部署配置。JBoss是一个根据LGPL许可证提供的开源应用服务器。当然，选择此应用服务器并不表示在J2EE容器中使用编译器和/或运行时的要求或偏好。还有其他优质的J2EE应用服务器可供选择，可能更适合运行此示例或类似的应用程序。</p>
				<p>完整的示例代码可以在发行版的“examples/terminalsvc”文件夹中找到。不需要J2EE容器的独立版本在“examples/terminalsvc-jse”中。</p>
				<div class="sect3" lang="en-US">
					<div class="titlepage">
						<div>
							<div>
								<h4 class="title"><a id="examples-terminalsvc-j2ee-running"></a>23.9.5.1. 运行示例</h4>
							</div>
						</div>
					</div>
					<p>预构建的EAR文件包含用于部署到JBoss应用服务器的MDB，并带有默认的部署选项。JBoss的默认配置提供了该示例使用的2个队列：queue/A和queue/B。queue/B用于将事件发送到MDB，而queue/A用于将监听器接收到的任何数据反馈给语句。</p>
					<p>可以通过将“examples/terminalsvc/terminalsvc-ear”文件夹中的ear文件复制到位于JBoss主目录下“standalone/deployments”中的JBoss部署目录来部署该应用程序。</p>
					<p>该示例包含一个事件模拟器和一个事件接收器，可以从命令行调用。有关模拟器的更多信息，请参阅“examples/terminalsvc/etc”文件夹中的README文件以及Windows和Unix的启动脚本和文档集。</p>
				</div>
				<div class="sect3" lang="en-US">
					<div class="titlepage">
						<div>
							<div>
								<h4 class="title"><a id="examples-terminalsvc-j2ee-building"></a>23.9.5.2. 构建示例</h4>
							</div>
						</div>
					</div>
					<p>该示例需要Maven 2进行构建。要构建该示例，请将目录更改为“examples/terminalsvc”文件夹，然后输入“mvn package”。这些说明已在JBoss AS 7.1.1和Maven 3.0.4上进行了测试。</p>
					<p>Maven构建将EAR文件打包，以便使用默认部署选项部署到JBoss应用服务器。</p>
				</div>
				<div class="sect3" lang="en-US">
					<div class="titlepage">
						<div>
							<div>
								<h4 class="title"><a id="examples-terminalsvc-j2ee-running-sim"></a>23.9.5.3. 运行事件模拟器和接收器</h4>
							</div>
						</div>
					</div>
					<p>该示例还包含一个生成有意义事件的事件模拟器。可以通过“examples/terminalsvc/etc”目录中的命令“run_terminalsvc_sender.bat”（Windows）和“run_terminalsvc_sender.sh”（Linux）来运行模拟器。事件模拟器每秒生成一批至少200个事件。对于每批事件，模拟器有十分之一的概率为随机一个终端生成“故障”或“纸张不足”事件。模拟器每批生成100个随机终端ID，并为每个ID生成一个“办理登机手续”事件。然后为每个ID生成“已取消”或“已完成”事件。对于某个终端，它有千分之一的概率生成“故障”事件，而不是“已取消”或“已完成”事件。</p>
					<p>事件接收器监听MDB发出的队列中的警报，并将这些警报打印到控制台。可以通过“examples/terminalsvc/etc”目录中的命令“run_terminalsvc_receiver.bat”（Windows）和“run_terminalsvc_receiver.sh”（Linux）来运行接收器。在运行之前，请将“jboss-client.jar”文件从您的JBoss AS安装的bin目录复制到“terminalsvc/lib”文件夹。</p>
					<p>接收器和发送器代码使用“guest”作为用户，“pass”作为密码。使用JBoss的“add-user”脚本添加“guest”用户，并分配“guest”角色。 您的JBoss服务器可能需要使用“-c standalone-full.xml”启动，以使消息子系统可用。</p>
					<p>按如下方式向消息子系统配置中添加队列配置：</p>
					<pre class="">&lt;jms-queue name="queue_a"&gt;
  &lt;entry name="queue_a"/&gt;
  &lt;entry name="java:jboss/exported/jms/queue/queue_a"/&gt;
&lt;/jms-queue&gt;
&lt;jms-queue name="queue_b"&gt;
  &lt;entry name="queue_b"/&gt;
  &lt;entry name="java:jboss/exported/jms/queue/queue_b"/&gt;
&lt;/jms-queue&gt;</pre>
					<p>对于此示例，在消息子系统中禁用持久性，以免耗尽磁盘空间：</p>
					<pre class="">&lt;persistence-enabled&gt;false&lt;/persistence-enabled&gt;</pre>
				</div>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-assets-moving"></a>23.10. 资产跨区域移动 - 一个RFID示例</h2>
					</div>
				</div>
			</div>
			<p>这个来自RFID领域的示例处理位置报告事件。每个位置报告事件指示一个资产ID和该资产当前所在的区域。 该示例解决了这样一个问题：当一组给定的资产没有一起从一个区域移动到另一个区域时，必须发出警报。</p>
			<p>每个资产组由两条语句进行跟踪。跟踪由资产ID为{1, 2, 3}的资产组成的单个资产组的两条语句如下：</p>
			<pre class="">insert into CountZone_G1
select 1 as groupId, zone, count(*) as cnt
from LocationReport(assetId in 1, 2, 3)#unique(assetId)
group by zone

select Part.zone from pattern [
  every Part=CountZone_G1(cnt in (1,2)) -&gt;
    (timer:interval(10 sec)  and not CountZone_G1(zone=Part.zone, cnt in (0,3)))]</pre>
			<p>
				此示例的类可以在包 <code class="literal">com.espertech.esper.example.rfid</code> 中找到。
			</p>
			<p>此示例提供了一个基于Swing的图形用户界面（GUI），可以从命令行运行。 该GUI允许将构成一个资产组的三个RFID标签从一个区域拖放到另一个区域。每次您在屏幕上移动一个资产时，该示例都会向运行时发送一个事件，指示资产ID和当前区域。该示例检测在10秒内这三个资产是否没有在同一区域内会合，而是仍然分散在不同区域。 运行“run_rfid_swing.bat”（Windows）或“run_rfid_swing.sh”（Unix）以启动该示例的Swing GUI。</p>
			<p>该示例还提供了一个可以从命令行运行的模拟器。 模拟器根据命令行参数指定的数量生成一些资产组，并根据命令行参数指定的数量启动一些线程，以将位置报告事件发送到运行时。 运行“run_rfid_sim.bat”（Windows）或“run_rfid_sim.sh”（Unix）以启动RFID位置报告事件模拟器。 请参阅同一文件夹中的README文件以获取构建说明和命令行参数。</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-stockticker"></a>23.11. 股票行情</h2>
					</div>
				</div>
			</div>
			<p>股票行情（StockTicker）示例来自股票交易领域。该示例创建事件模式，以便根据价格和股票代码过滤股票行情事件。 当遇到股票行情事件的价格超出上下限范围时，该示例会简单地显示该股票行情事件。 价格范围本身是动态创建和更改的。这是通过一个重叠上下文实现的，该上下文使用价格限制事件来确定如何寻找价格波动。</p>
			<p>
				类 <code class="literal">StockTick</code> 和 <code class="literal">PriceLimit</code> 代表我们的事件。事件模式由类 <code class="literal">StockTickerEPLUtil</code> 创建。
			</p>
			<p>总结：</p>
			<div class="itemizedlist">
				<ul compact="compact">
					<li>
						<p>这是学习API并开始了解上下文和模式的好示例。</p>
					</li>
					<li>
						<p>当价格限制事件到达时，分配能够找到价格波动的模式。</p>
					</li>
					<li>
						<p>针对股票行情事件中的事件属性（如股票代码和价格），有简单且高性能的过滤表达式。</p>
					</li>
				</ul>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-matchmaker"></a>23.12. 配对器</h2>
					</div>
				</div>
			</div>
			<p>在配对器（MatchMaker）示例中，每个移动用户都有一个X和Y坐标位置、一组属性（性别、头发颜色、年龄范围）以及一组用于匹配的偏好（每个属性对应一个偏好）。此示例创建的事件模式的任务是检测在给定范围内彼此接近，并且属性与偏好相匹配的移动用户。</p>
			<p>
				表示移动用户的事件类是 <code class="literal">MobileUserBean</code>。<code class="literal">MatchMakerEPL</code> 类包含用于检测匹配的模式。
			</p>
			<p>总结：</p>
			<div class="itemizedlist">
				<ul compact="compact">
					<li>
						<p>使用重叠上下文来查找匹配的移动用户事件</p>
					</li>
					<li>
						<p>对移动用户事件的X和Y属性使用范围匹配</p>
					</li>
				</ul>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-namedwindowquery"></a>23.13. 命名窗口查询</h2>
					</div>
				</div>
			</div>
			<p>
				此示例处理非常简单的温度传感器事件，这些事件由 <code class="literal">java.util.Map</code> 表示。它创建一个命名窗口，并向其中填充大量事件。然后，它通过on-select执行大量预定义的语句，并针对该命名窗口执行大量即发即弃的查询，并报告执行时间。
			</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-virtualdw"></a>23.14. 虚拟数据窗口示例</h2>
					</div>
				</div>
			</div>
			<p>虚拟数据窗口是一种扩展API，用于集成外部存储并将其中的数据公开为命名窗口。</p>
			<p>
				有关示例代码、编译和运行脚本，请参阅 <code class="literal">virtualdw</code> 文件夹。
			</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-cycledetect"></a>23.15. 循环检测示例</h2>
					</div>
				</div>
			</div>
			<p>
				此示例在扩展API部分，特别是聚合多功能开发中也有讨论。 该示例使用 <code class="literal">jgrapht</code> 库来解决循环检测问题，检测账户之间交易中的循环。
			</p>
			<p>
				有关示例代码、编译和运行脚本，请参阅 <code class="literal">examples/cycledetect</code> 文件夹。
			</p>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-qossla"></a>23.16. 服务质量</h2>
					</div>
				</div>
			</div>
			<p>此示例开发了一些代码，用于测量服务质量级别，例如服务级别协议（SLA）相关的指标。 服务级别协议是两方之间的合同，定义了服务约束，例如服务操作的最大延迟或错误率。</p>
			<p>该示例测量和监控每个客户和操作的操作延迟和错误计数。当我们的某个操作超出这些约束时，您希望立即收到警报。此外，您希望有一些监控措施，检查我们服务的运行状况，并提供有关操作使用情况的一些信息。</p>
			<p>您需要检查的一些约束条件是：</p>
			<div class="itemizedlist">
				<ul compact="compact">
					<li>
						<p>某些操作的延迟（完成时间）始终小于X秒。</p>
					</li>
					<li>
						<p>在Z次操作调用中，延迟平均值始终小于Y秒。</p>
					</li>
				</ul>
			</div>
			<p>
				<code class="literal">com.espertech.esper.example.qos_sla.events.OperationMeasurement</code> 事件类及其延迟和状态属性是用于SLA分析的主要事件。另一个事件 <code class="literal">LatencyLimit</code> 用于动态设置延迟限制。
			</p>
			<p>
				<code class="literal">com.espertech.esper.example.qos_sla.monitor.AverageLatencyMonitor</code> 创建一条语句，计算过去100个事件中每个客户和操作的延迟统计信息。<code class="literal">DynaLatencySpikeMonitor</code> 使用事件模式来监听动态设置限制的延迟峰值。<code class="literal">ErrorRateMonitor</code> 在事件模式中使用定时器 <code class="literal">'at'</code> 操作符，该操作符定期唤醒并轮询过去10分钟内的错误率。<code class="literal">ServiceHealthMonitor</code> 仅在发生3次错误时发出警报，而 <code class="literal">SpikeAndErrorMonitor</code> 在固定延迟被超过或报告错误状态时发出警报。
			</p>
			<p>总结：</p>
			<div class="itemizedlist">
				<ul compact="compact">
					<li>
						<p>此示例将事件模式与用于事件流分析的语句相结合。</p>
					</li>
					<li>
						<p>
							展示了在事件模式中使用定时器 <code class="literal">'at'</code> 操作符和跟随操作符 <code class="literal">-&gt;</code>。
						</p>
					</li>
					<li>
						<p>概述了基本语句。</p>
					</li>
					<li>
						<p>展示了如何从语句中提取数据，而不是订阅语句发布的事件。</p>
					</li>
				</ul>
			</div>
		</div>
		<div class="sect1" lang="en-US">
			<div class="titlepage">
				<div>
					<div>
						<h2 class="title"><a id="examples-trivia"></a>23.17. 冷知识极客俱乐部</h2>
					</div>
				</div>
			</div>
			<p>此示例是为2011年DEBS会议开发的，展示了如何在EPL中实现冷知识问答游戏的计分规则。</p>
			<p>
				实现所有计分规则的模块位于 <code class="literal">etc</code> 文件夹中的 <code class="literal">trivia.epl</code> 文件中。运行该解决方案只需要这些EPL代码，无需任何自定义函数。
			</p>
			<p>
				冷知识极客俱乐部规则（要求）在 <code class="literal">etc</code> 文件夹中的 <code class="literal">trivia_scoring_requirements.htm</code> 文件中提供。
			</p>
			<p>
				提供的实现根据 <code class="literal">trivia_test_questions_small.htm</code> 和 <code class="literal">trivia_test_questions_large.htm</code> 中提供的数据对问题、答案和计分进行测试。
			</p>
		</div>
	</div>
	<ul class="docnav">
		<li class="previous"><a accesskey="p" href="extension.html"><strong>上一页</strong>第22章. 集成与扩展</a></li>
		<li class="up"><a accesskey="u" href="#"><strong>返回顶部</strong></a></li>
		<li class="home"><a accesskey="h" href="index.html"><strong>首页</strong></a></li>
		<li class="next"><a accesskey="n" href="performance.html"><strong>下一页</strong>第24章. 性能</a></li>
	</ul>
</body>

</html>